//
//  WXSSleepManager.m
//  SleepBooks
//
//  Created by 王勇 on 16/9/20.
//  Copyright © 2016年 rimi. All rights reserved.
//

#import "WXSSleepManager.h"
#import "WXSMotionSensor.h"
#import "WXSRecorderManger.h"

#import "WXSSleepInfoModel.h"
#import "WXSSleepStatusModel.h"
#import "WXSDreamTalkModel.h"

static const NSTimeInterval kTimeFromShallowSleepToDeepSleep = 3;//默认从浅睡眠进入深度睡眠时间
static const NSTimeInterval kTimeFromAwakeToShallowSleep = 3;//最短入睡时间

@interface WXSSleepManager ()

@property (nonatomic,strong)WXSSleepInfoModel *sleepInfoModel;

@property (nonatomic,strong)WXSShallowSleepStatusModel *shallowModel;
@property (nonatomic,strong)WXSDeepSleepStatusModel *deepModel;
@property (nonatomic,strong)WXSAwakeSleepStatusModel *awakeModel;

@property (nonatomic,strong)NSTimer *myTimer;

@property (nonatomic,strong)NSString *archieveFilePath;

@property (nonatomic,strong)NSString *storageDirectory;

@end

static WXSSleepManager *manager = nil;

@implementation WXSSleepManager{


}

+(instancetype)defaultManager{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[self alloc]init];
    });
    
    return manager;
}

-(void)beginSleep{
    WXSLog(@"开始睡眠！");
    
    //添加观察者
//    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(enterShallowSleepStatus:) name:@"EnterShallowStatusNotification" object:nil];
//    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(enterDeepSleepStatus:) name:@"EnterDeepStatusNotification" object:nil];
//    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(enterAwakeStatus:) name:@"EnterAwakeStatusNotification" object:nil];
    
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(getAudioFilesWithNotiInfo:) name:@"SaveAudioModelsNotification" object:nil];
    [self enterAwakeStatus:nil];
    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:kTimeFromAwakeToShallowSleep target:self selector:@selector(enterShallowSleepStatus:) userInfo:nil repeats:NO];
    self.sleepInfoModel.startTime = [NSDate date];
    
    //清除数据
    [self.sleepInfoModel.deepModels removeAllObjects];
    [self.sleepInfoModel.shallowModels removeAllObjects];
    [self.sleepInfoModel.awakeModels removeAllObjects];
    [self.sleepInfoModel.sleepStatusSequence removeAllObjects];

    //获取本次睡眠数据文件存储路径
    self.sleepInfoModel.storagePath = [self createArchieveFilePath];
    
    //激活动作感应器
    [[WXSMotionSensor sensor]enableMotionSensor];
    //激活录音机
    [[WXSRecorderManger defaultManager]startRecordingWithFilePath:self.storageDirectory completionHandler:nil];
}

-(void)endSleep{
    WXSLog(@"结束睡眠！");
    
    if (self.myTimer) {
        [self invalidateTimer:self.myTimer];
    }
    self.sleepInfoModel.endTime = [NSDate date];
    
    //结束所有睡眠状态
    if (self.awakeModel) {
        [self.awakeModel endAwake];
        self.awakeModel = nil;
    }
    
    if (self.shallowModel) {
        [self.shallowModel endShallowSleep];
        self.shallowModel = nil;
    }
    
    if (self.deepModel) {
        [self.deepModel endDeepSleep];
        self.deepModel = nil;
    }
    
    //开始统计所有数据
    self.sleepInfoModel.totalSleepingTime = [self.sleepInfoModel.endTime timeIntervalSinceDate:self.sleepInfoModel.startTime];
        WXSLog(@"睡眠总时长：%.2f",self.sleepInfoModel.totalSleepingTime);
        WXSLog(@"浅度睡眠总时长：%.2f",self.sleepInfoModel.shallowSleepingTime);
        WXSLog(@"深度睡眠总时长：%.2f",self.sleepInfoModel.deepSleepingTime);
        WXSLog(@"醒来总时长：%.2f",self.sleepInfoModel.awakeTime);
    
        NSLog(@"深度睡眠详情：%@",self.sleepInfoModel.deepModels.description);
        NSLog(@"浅度睡眠详情：%@",self.sleepInfoModel.shallowModels.description);
        NSLog(@"醒来详情：%@",self.sleepInfoModel.awakeModels.description);
    WXSLog(@"总体睡眠状况：%@",self.sleepInfoModel.sleepStatusSequence);
    

    
        //移除观察者
        //    [[NSNotificationCenter defaultCenter]removeObserver:self];
        
        //终止动作感应器
        [[WXSMotionSensor sensor]disableMotionSensor];
        //终止录音机
        [[WXSRecorderManger defaultManager]stopRecording:nil];
//    });
}

-(void)enderDeepSleepStatus:(id)sender{
    
    //先终止其他睡眠状态
    if (self.awakeModel) {
        [self.awakeModel endAwake];
        self.awakeModel = nil;
    }
    
    if (self.shallowModel) {
        [self.shallowModel endShallowSleep];
        self.shallowModel = nil;
    }
    
    if ([sender isKindOfClass:[NSTimer class]]) {//由timer调用，表示没有出现干扰，则应当进入深度睡眠
        WXSLog(@"由timer调用，进入深度睡眠状态！");
        //进行其他操作
        [self invalidateTimer:self.myTimer];
    }
    
    WXSDeepSleepStatusModel *deepModel = [WXSDeepSleepStatusModel startDeepSleep];
    [self.sleepInfoModel.deepModels addObject:deepModel];
    [self.sleepInfoModel.sleepStatusSequence addObject:deepModel];
    self.deepModel = deepModel;
}

-(void)enterShallowSleepStatus:(id)sender{
    NSLog(@"触发浅睡眠状态！");
    //如果之前是在醒来状态，结束醒来状态，并记录
    if (self.awakeModel) {
        [self.awakeModel endAwake];
        self.awakeModel = nil;
    }
    
    //如果之前是在深度睡眠状态，结束深度睡眠状态，并记录
    if (self.deepModel) {
        [self.deepModel endDeepSleep];
        self.deepModel = nil;
    }
    
    if ([sender isKindOfClass:[NSTimer class]]) {//被timer调用，表示在入睡期且没有受到干扰。可以直接进入浅度睡眠期。
        WXSLog(@"入睡期且没有受到干扰。进入浅度睡眠期！");
        [self invalidateTimer:self.myTimer];
        self.myTimer = [NSTimer scheduledTimerWithTimeInterval:kTimeFromShallowSleepToDeepSleep target:self selector:@selector(enderDeepSleepStatus:) userInfo:nil repeats:NO];
    
    }else{//被其他对象调用，表示人为的状态切换
        if (self.myTimer) {//timer还没有被销毁，表示浅睡眠到深睡眠过程中有了扰动。会重新回到浅度睡眠初始点
            WXSLog(@"浅睡眠到深睡眠过程中有了扰动。会重新回到浅度睡眠初始点");
            [self invalidateTimer:self.myTimer];
        }
        self.myTimer = [NSTimer scheduledTimerWithTimeInterval:kTimeFromShallowSleepToDeepSleep target:self selector:@selector(enderDeepSleepStatus:) userInfo:nil repeats:NO];
    }
    
    if (self.shallowModel) {//如果之前没有退出浅睡眠状态，则不需要再重新创建浅睡眠模型
        return;
    }
    
    WXSShallowSleepStatusModel *shallowModel = [WXSShallowSleepStatusModel startShallowSleep];
    [self.sleepInfoModel.shallowModels addObject:shallowModel];
    [self.sleepInfoModel.sleepStatusSequence addObject:shallowModel];

    self.shallowModel = shallowModel;
}

-(void)enterAwakeStatus:(id)sender{
//    if ([sender isKindOfClass:NSClassFromString(@"NSConcreteNotification")]) {
//        [[NSNotificationCenter defaultCenter]removeObserver:self];
//    }
    
//    NSObject *lock
//    @synchronized (self) {
        //如果之前是在浅度睡眠状态，结束浅度睡眠状态，并记录
        if (self.shallowModel) {
            [self.shallowModel endShallowSleep];
            self.shallowModel = nil;
        }
        
        //如果之前是在深度睡眠状态，结束深度睡眠状态，并记录
        if (self.deepModel) {
            [self.deepModel endDeepSleep];
            self.deepModel = nil;
        }
        
        
        if ([sender isKindOfClass:[NSTimer class]]) {
            
        }else{//外界扰动造成的
            NSLog(@"受到外界扰动");
            if (self.myTimer) {//计时还没有结束就被调用，表示入睡过程受到外界干扰，重新回到清醒初始状态
                WXSLog(@"入睡过程中受到干扰，回到清醒初始状态");
                [self invalidateTimer:self.myTimer];
            }
//            self.myTimer = [NSTimer scheduledTimerWithTimeInterval:kTimeFromAwakeToShallowSleep target:self selector:@selector(enterShallowSleepStatus:) userInfo:nil repeats:NO];
            self.myTimer = [NSTimer timerWithTimeInterval:kTimeFromAwakeToShallowSleep target:self selector:@selector(enterShallowSleepStatus:) userInfo:nil repeats:NO];
            [[NSRunLoop currentRunLoop]addTimer:self.myTimer forMode:NSRunLoopCommonModes];
        }
        
        if (self.awakeModel) {//如果之前就已经在醒来状态，不做任何操作，退出
            return;
        }
        
        WXSAwakeSleepStatusModel *awakeModel = [WXSAwakeSleepStatusModel startAwake];
        [self.sleepInfoModel.awakeModels addObject:awakeModel];
        [self.sleepInfoModel.sleepStatusSequence addObject:awakeModel];
        self.awakeModel = awakeModel;
//    }
    
}

-(WXSSleepInfoModel *)sleepInfoWithStartDate:(NSDate *)date{
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    path = [path stringByAppendingPathComponent:@"MySleepInfo"];
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"yyyy-MM-dd-HH:mm:ss"];
    path = [path stringByAppendingPathComponent:[formatter stringFromDate:date]];
    
    
    NSMutableData *data = [NSMutableData dataWithContentsOfFile:path];
    WXSSleepInfoModel *model = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    return model;
}


-(void)removeAudioFileAtPath:(NSString *)path{
    NSError *error = nil;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:path]) {
        return;
    }
    [fileManager removeItemAtPath:path error:&error];
    if (error) {
        NSLog(@"Failed to delete file. Error:%@",error.localizedDescription);
    }else{
        NSLog(@"Removed file successfully!");
    }
}

-(void)removeAudioFilesAtDate:(NSDate *)date{

    NSString *path =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
    NSString *fullPath = [path stringByAppendingPathComponent:@"MySleepInfo"];
    
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"yyyy-MM-dd-HH:mm:ss"];
    NSString *dateString = [formatter stringFromDate:date];
    
    NSString *directoryPath = [fullPath stringByAppendingPathComponent:dateString];
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isDirectory = NO;
    if ([fileManager fileExistsAtPath:directoryPath isDirectory:&isDirectory]) {
        if (isDirectory) {
            [fileManager removeItemAtPath:directoryPath error:nil];
        }
    }
}

#pragma mark - Private
-(void)getAudioFilesWithNotiInfo:(NSNotification*)noti{
//    NSLog(@"info:%@",noti.userInfo);

    self.sleepInfoModel.dreamTalkModels = (NSMutableArray*)noti.userInfo[@"sleepTalks"];
    [self saveDataForTonight];
}


-(void)saveDataForTonight{
    

    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.sleepInfoModel];
    
    BOOL success = [data writeToFile:[self createArchieveFilePath] atomically:YES];
    if (success) {
        NSLog(@"归档成功！");
#warning 测试用
        WXSSleepInfoModel *mod = [self sleepInfoWithStartDate:self.sleepInfoModel.startTime];
        WXSDreamTalkModel *model = mod.dreamTalkModels.firstObject;
        NSLog(@"record Duration:%f,record startTime:%@,file path :%@",model.recordDuration,model.recordStartTime,model.modelFilePath);

    }else{
        NSLog(@"归档失败！");
    }
}

-(void)invalidateTimer:(NSTimer*)timer{
    [self.myTimer invalidate];
    self.myTimer = nil;
    
    WXSLog(@"timer has been invalidated");
}

#pragma mark Getter && Setter
-(WXSSleepInfoModel *)sleepInfoModel{
    if (!_sleepInfoModel) {
        _sleepInfoModel  = [[WXSSleepInfoModel alloc]init];
    }
    return _sleepInfoModel;
}

-(NSString *)createArchieveFilePath{
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    NSError *error = nil;
    path = [path stringByAppendingPathComponent:@"MySleepInfo"];
    [[NSFileManager defaultManager]createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:&error];
    if (error) {
        NSLog(@"创建文件夹错误！error:%@",error.localizedDescription);
    }
//    NSDate *currentDate = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"yyyy-MM-dd-HH:mm:ss"];
    NSString *dateString = [formatter stringFromDate:self.sleepInfoModel.startTime];
    
    NSString *directoryPath = [path stringByAppendingPathComponent:dateString];
    
    [[NSFileManager defaultManager]createDirectoryAtPath:directoryPath withIntermediateDirectories:NO attributes:nil error:&error];
    if (error) {
        NSLog(@"创建文件夹错误！error:%@",error.localizedDescription);
    }
    
    self.storageDirectory = directoryPath;
    
    NSString *finalPath = [directoryPath stringByAppendingString:dateString];
    return  finalPath;
}

@end
